package com.digdes.calendar.gwt.client.widget;

import com.digdes.calendar.gwt.client.dto.EventDTOImpl;
import com.digdes.calendar.gwt.client.service.CalendarService;
import com.digdes.calendar.gwt.client.service.CalendarServiceAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("deprecation")
public class WeekWidget extends Composite implements ClickListener {
    private final CalendarServiceAsync calendarService = GWT
            .create(CalendarService.class);
    private AbsolutePanel aPanel = new AbsolutePanel();
    private ScrollPanel scrollPanel;
    private Data data = new Data();
    public CellGridDay hourGrid;
    private Grid weekGrid;
    private FlexTable gridWeekHeader = new FlexTable();
    public DateUtil date = new DateUtil();
    private List<EventDTOImpl> eventDTOList = new ArrayList<EventDTOImpl>();
    private List<CellGridDay> gridInCellList = new ArrayList<CellGridDay>();
    private List<EventLabel> eventLabels = new ArrayList<EventLabel>();
    private ShowEventDBox eventDBox;

    public WeekWidget() {
        DockPanel outer = new DockPanel();
        setWidget(outer);
        gridWeekHeader.setWidth("930px");
        gridWeekHeader.setCellPadding(0);
        gridWeekHeader.setCellSpacing(0);
        gridWeekHeader.setStyleName("weekheader");

        scrollPanel = new ScrollPanel(aPanel);
        scrollPanel.setSize("1000px", "550px");
        scrollPanel.addStyleName("scrollDay");
        weekGrid = new Grid(24, 8);
        weekGrid.setHeight("550px");
        weekGrid.setWidth("980px");
        weekGrid.setCellPadding(0);
        weekGrid.setCellSpacing(0);
        aPanel.setSize("100%", "1200px");
        aPanel.add(weekGrid);

        DockPanel weekHeader = new DockPanel();
        weekHeader.add(gridWeekHeader, DockPanel.CENTER);

        Grid gLeft = new Grid(1, 1);
        gLeft.setStyleName("headerColor");
        gLeft.setCellPadding(0);
        gLeft.setCellSpacing(0);
        gLeft.setSize("60px", "25px");
        weekHeader.add(gLeft, DockPanel.WEST);
        Grid gRight = new Grid(1, 1);
        gRight.setStyleName("headerColor");
        gRight.setCellPadding(0);
        gRight.setCellSpacing(0);
        gRight.setSize("20px", "25px");
        weekHeader.add(gRight, DockPanel.EAST);

        outer.add(weekHeader, DockPanel.NORTH);
        outer.setCellHorizontalAlignment(weekHeader, HasAlignment.ALIGN_RIGHT);
        outer.add(scrollPanel, DockPanel.CENTER);

        outer.setStyleName("CalendarWidget");
        drawWeekCalendar();
    }

    public void drawWeekCalendar() {

        scrollPanel.scrollToTop();

        for (int i = 0; i < data.hours.length; i++) {
            weekGrid.setText(i, 0, data.hours[i]);
            weekGrid.getCellFormatter().setStyleName(i, 0, "hours");
            weekGrid.getCellFormatter().addStyleName(i, 0, "hoursSecond");
            weekGrid.getCellFormatter().addStyleName(i, 0, "cellRightBorder");
            for (int k = 1; k < 8; k++) {
                weekGrid.getCellFormatter().addStyleName(i, k, "cellRightBorder");
                hourGrid = new CellGridDay(2, 1);
                hourGrid.getCellFormatter().setStyleName(0, 0, "hoursFirst");
                hourGrid.getCellFormatter().setStyleName(1, 0, "hoursSecond");
                hourGrid.setWidth("100%");
                hourGrid.setHeight("50px");
                hourGrid.setCellPadding(0);
                hourGrid.setCellSpacing(0);
                weekGrid.setWidget(i, k, hourGrid);
                hourGrid.setDayWeek(k - 1);
                hourGrid.setHour(i);
                gridInCellList.add(hourGrid);
            }
        }
        //getEvents();
    }

    public void getEvents() {
        clearWeekWidget();
        int day = date.getDate().getDay();
        if (date.getDate().getDay() == 0) day = 6;
        int sDate = date.getDate().getDate() - (day - 1);
        int sMonth = date.getMonth();
        int fDate = sDate + 6;
        int fMonth = date.getMonth();
        int dayNextPrevMonth = date.getDaysInMonth(date.getYear(), date.getMonth() - 1);
        int numOfDays = date.getDaysInMonth(date.getYear(), date.getMonth());
        int dayNextMonth = 1;
        int k = 0;
        if (sDate < 1) {
            for (int iL = day - 1; iL > 0; iL--) {
                k--;
                if ((date.getDay() + k) < 1) {
                    sDate = dayNextPrevMonth;

                    dayNextPrevMonth--;
                }
            }
            sMonth = date.getMonth() - 1;
        }
        if (fDate > numOfDays) {
            k = 0;
            dayNextMonth = 1;
            for (int iR = day; iR < 7; iR++) {
                k++;
                if ((date.getDay() + k) > numOfDays) {
                    fDate = dayNextMonth;
                    dayNextMonth++;
                }
            }
            fMonth = date.getMonth() + 1;
        }

        String startDate = sDate + "." + (sMonth + 1) + "." + date.getYear();
        String finishDate = fDate + "." + (fMonth + 1) + "." + date.getYear();

        calendarService.getEventsBetween(startDate, finishDate, new AsyncCallback<ArrayList<EventDTOImpl>>() {
            public void onFailure(Throwable caught) {
            }

            public void onSuccess(ArrayList<EventDTOImpl> result) {
                eventDTOList.addAll(result);
                setEventInCellDay();
            }
        });
    }

    private void setDayMonthInHourGrid(int dayWeek, int dayMonth, int month) {
        for (CellGridDay c : gridInCellList)
            if (dayWeek == c.getDayWeek()) {
                c.setDayMonth(dayMonth);
                c.setMonth(month);
            }

    }

    public void setDataWeekHeader() {
        int k = 0;
        int numOfDays = date.getDaysInMonth(date.getYear(), date.getMonth());
        if (date.getDate().getDay() == 0) {
            gridWeekHeader.setText(0, 6, data.days[6] + ", " + (date.getDay()) +
                    "/" + (date.getMonth() + 1));
            setDayMonthInHourGrid(6, date.getDay(), date.getMonth() + 1);

            int dayNextPrevMonth = date.getDaysInMonth(date.getYear(), date.getMonth() - 1);
            for (int iL = 5; iL >= 0; iL--) {
                k--;
                if ((date.getDay() + k) < 1) {
                    gridWeekHeader.setText(0, iL, data.days[iL] + ", " + (dayNextPrevMonth) +
                            "/" + (date.getMonth()));
                    setDayMonthInHourGrid(iL, dayNextPrevMonth, date.getMonth());
                    dayNextPrevMonth--;
                } else {
                    gridWeekHeader.setText(0, iL, data.days[iL] + ", " + (date.getDay() + k) +
                            "/" + (date.getMonth() + 1));
                    setDayMonthInHourGrid(iL, date.getDay() + k, date.getMonth() + 1);
                }
            }
        }
        for (int i = 0; i < data.days.length; i++) {
            if ((date.getDate().getDay() - 1) == i) {
                gridWeekHeader.setText(0, i, data.days[i] + ", " + (date.getDay()) +
                        "/" + (date.getMonth() + 1));
                setDayMonthInHourGrid(i, date.getDay(), date.getMonth() + 1);

                int dayNextPrevMonth = date.getDaysInMonth(date.getYear(), date.getMonth() - 1);
                for (int iL = i - 1; iL >= 0; iL--) {
                    k--;
                    if ((date.getDay() + k) < 1) {
                        gridWeekHeader.setText(0, iL, data.days[iL] + ", " + dayNextPrevMonth +
                                "/" + (date.getMonth()));
                        setDayMonthInHourGrid(iL, dayNextPrevMonth, date.getMonth());
                        dayNextPrevMonth--;
                    } else {
                        gridWeekHeader.setText(0, iL, data.days[iL] + ", " + (date.getDay() + k) +
                                "/" + (date.getMonth() + 1));
                        setDayMonthInHourGrid(iL, date.getDay() + k, date.getMonth() + 1);
                    }
                }
                k = 0;
                int dayNextMonth = 1;
                for (int iR = i + 1; iR < data.days.length; iR++) {
                    k++;
                    if ((date.getDay() + k) > numOfDays) {
                        gridWeekHeader.setText(0, iR, data.days[iR] + ", " + dayNextMonth +
                                "/" + (date.getMonth() + 2));
                        setDayMonthInHourGrid(iR, dayNextMonth, date.getMonth() + 2);
                        dayNextMonth++;
                    } else {
                        gridWeekHeader.setText(0, iR, data.days[iR] + ", " + (date.getDay() + k) +
                                "/" + (date.getMonth() + 1));
                        setDayMonthInHourGrid(iR, date.getDay() + k, date.getMonth() + 1);
                    }
                }
            }

        }
    }

    private void clearWeekWidget() {
        scrollPanel.scrollToTop();
        eventDTOList.clear();
        for (EventLabel label : eventLabels) {
            label.removeFromParent();
            RootPanel.get().remove(label);
        }
    }

    int moveLeft = 255;
    int moveTop = 78 + gridWeekHeader.getOffsetHeight();
    int left = 0;

    public void setEventInCellDay() {

        for (CellGridDay c : gridInCellList) {
            left = 0;
            c.getEventDTOList().clear();
            if (c.getDayMonth() == date.getNowDay()) {
                c.addStyleName("today");
            } else c.removeStyleName("today");
            int countEvent = 0;
            for (EventDTOImpl eventDTO : eventDTOList) {
                if (eventDTO.getDateStart().getDate() == eventDTO.getDateFinish().getDate()
                        && eventDTO.getDateStart().getDate() == c.getDayMonth()
                        && eventDTO.getDateStart().getMonth() + 1 == c.getMonth()
                        && (eventDTO.getDateStart().getYear() + 1900) == date.getYear()) {
                    if (eventDTO.getDateStart().getHours() == c.getHour()) {
                        countEvent++;
                        c.getEventDTOList().add(eventDTO);
                    }
                }
            }
            for (EventDTOImpl e : c.getEventDTOList()) {
                drawEvent(c, e, countEvent);
            }
            c.setLeft(0);
        }
    }

    private void drawEvent(CellGridDay c, EventDTOImpl e, int countEvent) {
        EventLabel label = new EventLabel(e);
        String title = e.getNameEvent() + "\n" + e.getDateStart().getHours() + ":" +
                date.addZeroInMinutes(e.getDateStart().getMinutes()) +
                " - " + e.getDateFinish().getHours() + ":" +
                date.addZeroInMinutes(e.getDateFinish().getMinutes());
        label.setStyleName("EventLabelDay");
        float minutes = (float) ((e.getDateFinish().getMinutes() - e.getDateStart().getMinutes()) * 0.8);
        int minutesStart = (int) (e.getDateStart().getMinutes() * 0.8);
        label.setHeight(String.valueOf((e.getDateFinish().getHours() -
                e.getDateStart().getHours()) * 50 + minutes - 3));
        label.setWidth(String.valueOf((Util.WIDTH_WEEK_CELL / countEvent) - 6));
        label.setText(title);
        label.setTitle(title);
        label.addClickListener(this);
        aPanel.add(label, c.getAbsoluteLeft() - moveLeft + c.getLeft(),
                minutesStart + c.getAbsoluteTop() - moveTop);
        left += (Util.WIDTH_WEEK_CELL / countEvent);
        c.setLeft(left);
        eventLabels.add(label);

    }

    public void onClick(Widget sender) {
        final EventLabel label = (EventLabel) sender;
        eventDBox = new ShowEventDBox(label.getEventDTO());
        eventDBox.deleteBtn.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                deleteEvent(label);
            }
        });
        eventDBox.center();
    }

    private void deleteEvent(final EventLabel label) {
        eventDBox.deleteEvent(label, eventLabels);
        for (CellGridDay c : gridInCellList) {
            c.getEventDTOList().remove(label.getEventDTO());
        }
    }
}
